package com.kelab.dify.service;

import com.kelab.dify.config.DifyConfig;
import com.kelab.dify.exception.DifyException;
import com.kelab.dify.model.workflow.WorkflowRequest;
import com.kelab.dify.model.workflow.WorkflowResponse;
import com.kelab.dify.service.base.BaseService;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

/**
 * 工作流服务类
 * 提供Workflow API的所有功能
 * 
 * @author kelab
 * @version 1.0
 */
public class WorkflowService extends BaseService {
    
    private static final Logger logger = LoggerFactory.getLogger(WorkflowService.class);
    
    private static final String WORKFLOWS_RUN_ENDPOINT = "workflows/run";
    private static final String WORKFLOWS_RUNS_ENDPOINT = "workflows/runs";
    
    /**
     * 构造函数
     * 
     * @param httpClient HTTP客户端
     * @param objectMapper JSON映射器
     * @param config 配置信息
     */
    public WorkflowService(OkHttpClient httpClient, ObjectMapper objectMapper, DifyConfig config) {
        super(httpClient, objectMapper, config);
    }
    
    /**
     * 运行工作流（阻塞模式）
     * 
     * @param request 工作流请求
     * @return 工作流响应
     * @throws DifyException 如果请求失败
     */
    public WorkflowResponse runWorkflow(WorkflowRequest request) throws DifyException {
        request.setResponseMode("blocking");
        
        String json = toJson(request);
        RequestBody body = RequestBody.create(json, JSON_MEDIA_TYPE);
        
        Request httpRequest = new Request.Builder()
                .url(config.getFullUrl(WORKFLOWS_RUN_ENDPOINT))
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .build();
        
        try (Response response = httpClient.newCall(httpRequest).execute()) {
            return handleResponse(response, WorkflowResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to run workflow", e);
        }
    }
    
    /**
     * 运行工作流（流式模式）
     * 
     * @param request 工作流请求
     * @param onMessage 消息回调函数
     * @param onError 错误回调函数
     * @return CompletableFuture，可用于等待流式响应完成
     * @throws DifyException 如果请求失败
     */
    public CompletableFuture<Void> runWorkflowStream(WorkflowRequest request,
                                                    Consumer<WorkflowResponse> onMessage,
                                                    Consumer<Throwable> onError) throws DifyException {
        request.setResponseMode("streaming");
        
        String json = toJson(request);
        RequestBody body = RequestBody.create(json, JSON_MEDIA_TYPE);
        
        Request httpRequest = new Request.Builder()
                .url(config.getFullUrl(WORKFLOWS_RUN_ENDPOINT))
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "text/event-stream")
                .build();
        
        CompletableFuture<Void> future = new CompletableFuture<>();
        
        EventSourceListener listener = new EventSourceListener() {
            @Override
            public void onOpen(EventSource eventSource, Response response) {
                logger.debug("Workflow SSE connection opened");
            }
            
            @Override
            public void onEvent(EventSource eventSource, String id, String type, String data) {
                try {
                    if (data != null && !data.trim().isEmpty()) {
                        WorkflowResponse workflowResponse = objectMapper.readValue(data, WorkflowResponse.class);
                        onMessage.accept(workflowResponse);
                        
                        // 检查是否为结束事件
                        if ("workflow_finished".equals(workflowResponse.getEvent()) ||
                            "workflow_failed".equals(workflowResponse.getEvent())) {
                            future.complete(null);
                        }
                    }
                } catch (Exception e) {
                    logger.error("Error parsing workflow SSE data: {}", data, e);
                    onError.accept(e);
                    future.completeExceptionally(e);
                }
            }
            
            @Override
            public void onClosed(EventSource eventSource) {
                logger.debug("Workflow SSE connection closed");
                if (!future.isDone()) {
                    future.complete(null);
                }
            }
            
            @Override
            public void onFailure(EventSource eventSource, Throwable t, Response response) {
                logger.error("Workflow SSE connection failed", t);
                onError.accept(t);
                future.completeExceptionally(t);
            }
        };
        
        EventSource eventSource = EventSources.createFactory(httpClient).newEventSource(httpRequest, listener);
        
        // 设置超时处理
        future.whenComplete((result, throwable) -> {
            eventSource.cancel();
        });
        
        return future;
    }
    
    /**
     * 获取工作流运行状态
     * 
     * @param runId 运行ID
     * @param user 用户标识
     * @return 工作流运行状态
     * @throws DifyException 如果请求失败
     */
    public WorkflowRunResponse getWorkflowRun(String runId, String user) throws DifyException {
        String url = config.getFullUrl(WORKFLOWS_RUNS_ENDPOINT + "/" + runId) + "?user=" + user;
        
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, WorkflowRunResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get workflow run", e);
        }
    }
    
    /**
     * 获取工作流运行历史
     * 
     * @param user 用户标识
     * @param lastId 最后一个运行ID（可选）
     * @param limit 限制数量（可选）
     * @return 工作流运行历史
     * @throws DifyException 如果请求失败
     */
    public WorkflowRunsResponse getWorkflowRuns(String user, String lastId, Integer limit) throws DifyException {
        StringBuilder urlBuilder = new StringBuilder(config.getFullUrl(WORKFLOWS_RUNS_ENDPOINT));
        urlBuilder.append("?user=").append(user);
        
        if (lastId != null && !lastId.isEmpty()) {
            urlBuilder.append("&last_id=").append(lastId);
        }
        if (limit != null && limit > 0) {
            urlBuilder.append("&limit=").append(limit);
        }
        
        Request request = new Request.Builder()
                .url(urlBuilder.toString())
                .get()
                .addHeader("Authorization", config.getAuthorizationHeader())
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, WorkflowRunsResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to get workflow runs", e);
        }
    }
    
    /**
     * 停止工作流运行
     * 
     * @param runId 运行ID
     * @param user 用户标识
     * @return 停止结果
     * @throws DifyException 如果请求失败
     */
    public WorkflowStopResponse stopWorkflowRun(String runId, String user) throws DifyException {
        String url = config.getFullUrl(WORKFLOWS_RUNS_ENDPOINT + "/" + runId + "/stop");
        
        String json = String.format("{\"user\":\"%s\"}", user);
        RequestBody body = RequestBody.create(json, JSON_MEDIA_TYPE);
        
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .addHeader("Authorization", config.getAuthorizationHeader())
                .addHeader("Content-Type", "application/json")
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            return handleResponse(response, WorkflowStopResponse.class);
        } catch (IOException e) {
            throw new DifyException("Failed to stop workflow run", e);
        }
    }
    
    // 内部响应类定义
    public static class WorkflowRunResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class WorkflowRunsResponse {
        // 根据实际API响应结构定义字段
    }
    
    public static class WorkflowStopResponse {
        // 根据实际API响应结构定义字段
    }
}